import json
from datetime import datetime
from flask import current_app
from werkzeug.security import generate_password_hash, check_password_hash

from create_app import db


class BaseModel(db.Model):
    __abstract__ = True

    id = db.Column(db.Integer, primary_key=True)
    created_at = db.Column(db.DateTime, default=datetime.now)
    updated_at = db.Column(db.DateTime, default=datetime.now, onupdate=datetime.now)

    def __repr__(self):
        return f'<{self.__class__} {self.id}>'


class User(BaseModel):
    __tablename__ = 'users'

    username = db.Column(db.String(80), unique=True)
    email = db.Column(db.String(120), unique=True)
    password_hash = db.Column(db.String(256))

    def __init__(self, username, email, password_hash):
        super().__init__()
        self.username = username
        self.email = email
        self.password_hash = password_hash

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)

    @classmethod
    def add(cls, data):
        obj = cls(**data)
        try:
            db.session.add(obj)
            db.session.commit()
            return obj.id
        except Exception as e:
            current_app.logger.error(str(e))
            db.session.rollback()
            return

    @classmethod
    def delete(cls, id):
        obj = cls.query.get(id)
        if obj:
            try:
                db.session.delete(obj)
                db.session.commit()
            except Exception as e:
                current_app.logger.error(str(e))
                db.session.rollback()
            return obj.id

    @classmethod
    def update(cls, id, data):
        obj = cls.query.get(id)
        if obj:
            for k, v in data.items():
                obj[k] = v
            return obj.id

    @classmethod
    def count(cls):
        return cls.query.count()

    @classmethod
    def get_pages(cls, page_number, per_page):
        users = cls.query.paginate(page=page_number, per_page=per_page)
        return users

    @classmethod
    def get_sorted(cls, by_col, asc=True):
        sorted_by_col = getattr(cls, by_col)
        if sorted_by_col:
            if asc:
                sorted_users = cls.query.order_by(sorted_by_col.asc()).all()
            else:
                sorted_users = cls.query.order_by(sorted_by_col.desc()).all()
            return sorted_users
        else:
            return

    @classmethod
    def get(cls, id, email):
        if not id and not email:
            return cls.query.all()
        if id and not email:
            return cls.query.get(id)
        if email and not id:
            return cls.query.filter(cls.email.like(f'%{email}%')).first()
        return cls.query.all()